/** 
* @Title: TraditionalThreadCommunication.java 
* @Package com.lh.threadtest.t4 
* @Description: TODO
* @author Liu 
* @date 2018年1月15日 下午9:28:23 
* @version V1.0 
*/
package com.lh.threadtest.t10;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/** 
* @ClassName: TraditionalThreadCommunication 
* @Description: 传统线程同步通信技术
* 
* 子线程循环10次，接着主线程循环100次，接着又回到子线程循环10次，接着再回到主线程
* 又循环100次，如此循环50次，请写出程序。
* 
* 注意：
* 	Lock比传统线程模型中的synchronized方式更加面向对象，与生活中的锁类似，锁本身也应该是一个对象。
* 两个线程执行的代码片段要实现同步互斥的效果，它们必须用同一个Lock对象。锁是上在代表要操作的资源的类的内部方法中，
* 而不是线程代码中！
* 
* 总结：
* 	需要用到共同数据(包括同步锁)或共同算法的若干个方法应该归在同一个类中，这种设计正好体现了
* 高类聚和程序的健壮性。
* 
* @author Liu
* @date 2018年1月15日 下午9:28:23 
*  
*/
public class ConditionCommunication {
	public static void main(String[] args) {
		final Business business = new Business();
		
		new Thread(new Runnable() {
			public void run() {
				for(int i = 1; i <= 50; i++){
					try {
						business.sub(i);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			}
		}).start();
		
		for(int i = 1; i <= 50; i++){
			try {
				business.main(i);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
	
//不同点：	
//condition.business
//business
	
	//将具有类似功能的业务代码抽象到同一个类中
	//下面两个方法(sub/main)是互斥的，均是独立的一个同步模块，处于同一个互斥组(通过synchronized表明均属于同一个类，同一时刻只能有一个线程持有该锁)
	static class Business{
		Lock lock = new ReentrantLock();
		Condition condition = lock.newCondition();
		
		//主线程和子线程切换执行的一个标识
		boolean flag = true;
		
		void sub(int i) throws InterruptedException{
			lock.lock();
			try {
//				if(!flag){
				//循环和if功能相仿，但更加完备
				while(!flag){
					//使当前线程等待...
//					this.wait();
					condition.await();
				}
				
				for(int j = 1; j <= 10; j++){
					System.out.println("sub thread sequence of "  + j + ", loop of " + i);
				}
				
				flag = false;
				
				//唤醒其它正在等待的线程
//				this.notify();
				condition.signal();
			} finally {
				lock.unlock();
			}
		}
		
		void main(int i) throws InterruptedException{
			lock.lock();
			try {
//				if(flag){
				//循环和if功能相仿，但更加完备
				while(flag){
					//使当前线程等待...
//					this.wait();
					condition.await();
				}
				
				for(int j = 1; j <= 100; j++){
					System.out.println("main thread sequence of "  + j + ", loop of " + i);
				}
				
				flag = true;
				
				//唤醒其它正在等待的线程
//				this.notify();
				condition.signal();
			} finally {
				lock.unlock();
			}
		}
	}
}
